﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.IO;
using System.Net;
using System.Threading;
using Lextm.SharpSnmpLib;
using Lextm.SharpSnmpLib.Messaging;
using DevicesInt;
using TimeoutException = Lextm.SharpSnmpLib.Messaging.TimeoutException;

namespace t_vips_analizator
{
    public class T_VIPS : IDeviceInterface
    {
        private static List<string> _tempFiles = new List<string>();
        private static Dictionary<string, Dictionary<int, LogRecord>> _recordsFromTraps = new Dictionary<string, Dictionary<int, LogRecord>>();
        private static Dictionary<string, Mutex> _trapsMtx = new Dictionary<string, Mutex>();

        private class LogRecord
        {
            public enum LogVar
            {
                Severity = 0,
                AlarmName = 3,
                RefNumber = 4,
                SourceText = 8,
                Details = 9
            }

            //public static Dictionary<string, string> LogFiles;

            public const string UnitAsserted = ".1.3.6.1.4.1.22909.1.1.0.2";
            public const string UnitCleared = ".1.3.6.1.4.1.22909.1.1.0.3";
            public const string UnitEvent = ".1.3.6.1.4.1.22909.1.1.0.4";
            public static Dictionary<string, string> LogSeverities;

            private static void CreateSeverities()
            {
                LogSeverities = new Dictionary<string, string>(6);
                LogSeverities["1"] = "Cleared";
                LogSeverities["2"] = "Indeterminate";
                LogSeverities["3"] = "Warning";
                LogSeverities["4"] = "Minor";
                LogSeverities["5"] = "Major";
                LogSeverities["6"] = "Critical";
            }

            public enum ObjectIdType
            {
                Asserted,
                Cleared,
                Event,
                AssertedAndCleared
            }

            public string Severity = "";
            public string Name = "";
            public string Source = "";
            public string Details = "";
            public string OnTime = "";
            public string OffTime = "";
            public int RefNumber = -1;
            public ObjectIdType RecordType;


            public LogRecord()
            {
                CreateSeverities();
            }

            public LogRecord(string[] list)
            {
                CreateSeverities();
                CreateFromList(list);
            }

            public void CreateFromList(string[] list)
            {
                Severity = list[0];
                Name = list[1];
                Source = list[2];
                Details = list[3];
                OnTime = list[4];
                OffTime = list[5];
                RefNumber = Int32.Parse(list[6]);
            }

            public static Dictionary<int, LogRecord> ReadFile(string path)
            {
                var list = new Dictionary<int, LogRecord>();
                if (!File.Exists(path))
                    return list;
                try
                {
                    using (var sr = new StreamReader(path, Encoding.Default))
                    {
                        while (true)
                        {
                            var readLine = sr.ReadLine();
                            if (readLine == null)
                                break;
                            var record = new LogRecord(readLine.Split(';'));
                            if (record.RefNumber == -1 || record.OffTime != "")
                                continue;
                            list.Add(record.RefNumber, record);
                        }
                    }
                }
                catch (Exception ex)
                {
                    using (var f = new StreamWriter(path + "ERROR",false, Encoding.Default))
                    {
                        f.Write(ex.Message);
                    }
                }
                return list;
            }

            public static void CorrectList(ref Dictionary<int, LogRecord> oldList, Dictionary<int, LogRecord> list)
            {
                //var newList = new Dictionary<int, LogRecord>();
                foreach (var logRecord in list)
                {
                    //Новое событие
                    switch(logRecord.Value.RecordType)
                    {
                        //События нет в старом списке
                        case ObjectIdType.Asserted:
                            if (!oldList.ContainsKey(logRecord.Key))
                                oldList.Add(logRecord.Key, logRecord.Value);
                            break;

                        //Добавление времени исправления ошибки
                        case ObjectIdType.Cleared:
                            //Проверяет наличие записи с таким RefNumber
                            if(oldList.ContainsKey(logRecord.Key))
                                oldList[logRecord.Key].OffTime = logRecord.Value.OnTime;
                            break;

                        //Событие без длительности
                        case ObjectIdType.Event:
                            logRecord.Value.OffTime = logRecord.Value.OnTime;
                            if (!oldList.ContainsKey(logRecord.Key))
                                oldList.Add(logRecord.Key, logRecord.Value);
                            break;

                        //Событие произошло и исправилось
                        case ObjectIdType.AssertedAndCleared:
                            oldList[logRecord.Key] = logRecord.Value;
                            break;
                    }
                }
            }

            /// <summary>
            /// Создает временную папку и возвращает путь к ней.
            /// </summary>
            /// <param name="path"></param>
            /// <returns></returns>
            public static string GetTempFilePath(string path)
            {
                var str = path.Split('\\');
                var splitName = str[str.Length - 1].Split('_');
                var ret = new string[str.Length + 1];
                var directory = new string[str.Length];
                str.CopyTo(directory, 0);
                str.CopyTo(ret, 0);
                directory[directory.Length - 1] = "T_VIPS_temp";
                var sb = new StringBuilder();
                foreach (var s in directory)
                {
                    sb.Append(s + '\\');
                }
                var dir = sb.Remove(sb.Length - 1, 1).ToString();
                if (!Directory.Exists(dir))
                    Directory.CreateDirectory(dir);
                //ret[ret.Length] = ret[ret.Length - 1];
                ret[ret.Length - 2] = "T_VIPS_temp";
                ret[ret.Length - 1] = splitName[0] + "_" + splitName[2];
                sb = new StringBuilder();
                foreach (var s in ret)
                {
                    sb.Append(s + '\\');
                }
                return sb.Remove(sb.Length - 1, 1).ToString();
            }

            public static string GetDeviceNameFromPath(string path)
            {
                var fi = new FileInfo(path);
                var split = fi.Name.Split('_');
                var rtps = split[0];
                var devName = split[2].Split('.')[0];
                //var str = path.Split('_');
                return rtps + "_" + devName;
            }

            /// <summary>
            /// Для записи во временный файл необходимо добавить RefNumber.
            /// </summary>
            /// <returns></returns>
            public new string ToString()
            {
                return Severity + ";" + Name + ";" + Source + ";" + Details + ";" + OnTime + ";" + OffTime + ";";
            }
        }

        public static class StatusData
        {

            //static List<ObjectIdentifier> Params;
            //static List<Variable>[] vars;
            private const string Community = "public"; //Read Community
            static int _timeout = 800;                          //Timeout

            public static int Timeout
            {
                get { return _timeout; }
                set { _timeout = value; }
            }

            static void PrepairForVars(out List<ObjectIdentifier> Params, out List<Variable>[] vars)                        //SNMP OIDS for getstatus
            {
                Params = new List<ObjectIdentifier>(4)
                    {
                        new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.20.1.5"),         //Severity
                        new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.20.1.4"),         //Name
                        new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.20.1.8"),         //Source
                        new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.20.1.9")          //Details
                    };
                vars = new List<Variable>[4];
                for (int i = 0; i < vars.Length; i++)
                {
                    vars[i] = new List<Variable>();
                }
            }
            static void PrepairForLogs(out List<ObjectIdentifier> Params, out List<Variable>[] vars)                        //SNMP OIDS for getlog
            {
                Params = new List<ObjectIdentifier>(7)
                    {
                        new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.21.1.3"),
                        new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.21.1.6"),
                        new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.21.1.11"),
                        new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.21.1.13"),
                        new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.21.1.14"),
                        new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.21.1.2"),
                        new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.21.1.7")
                    };
                vars = new List<Variable>[7];
                for (int i = 0; i < vars.Length; i++)
                {
                    vars[i] = new List<Variable>();
                }
                vars[0].Add(new Variable(Params[0], new OctetString("Severity")));
                vars[1].Add(new Variable(Params[1], new OctetString("Name")));
                vars[2].Add(new Variable(Params[2], new OctetString("Source")));
                vars[3].Add(new Variable(Params[3], new OctetString("Details")));
                vars[4].Add(new Variable(Params[4], new OctetString("Time")));
                vars[5].Add(new Variable(Params[5], new OctetString("ObjectId")));
                vars[6].Add(new Variable(Params[6], new OctetString("RefNumber")));
                //vars[1].Add(new Variable(new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.21.1.6"), new OctetString("Name")));
                //vars[2].Add(new Variable(new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.21.1.11"), new OctetString("Source")));
                //vars[3].Add(new Variable(new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.21.1.13"), new OctetString("Details")));
                //vars[4].Add(new Variable(new ObjectIdentifier("1.3.6.1.4.1.22909.1.1.1.21.1.14"), new OctetString("Time")));
            }
            
            static List<Variable>[] GetData(string ip, IEnumerable<ObjectIdentifier> Params, List<Variable>[] vars)          //Retrieving variables from T-VIPS via SNMP
            {
                var receiver = new IPEndPoint(IPAddress.Parse(ip), 161);
                int i = 0;
                try
                {


                    foreach (ObjectIdentifier oi in Params)
                    {
                        int tryCount = 4;
                        while (--tryCount > 0)
                        {
                            try
                            {
                                Messenger.Walk(VersionCode.V2, receiver, new OctetString(Community), oi, vars[i], _timeout, WalkMode.WithinSubtree);
                                break;
                            }
                            catch (TimeoutException)
                            {

                            }
                            catch (IndexOutOfRangeException)
                            {

                            }
                        }
                        if (tryCount == 0)
                        {
                            //vars[0].Clear();
                            vars[0].Add(new Variable(new ObjectIdentifier("1.3")));
                            break;
                        }
                        i++;
                    }
                }
                catch (IndexOutOfRangeException)
                {
                    
                }
                return vars;
            }

            public static List<Variable>[] GetVariables(string ip)          //Return variables for getstatus
            {
                List<ObjectIdentifier> Params;
                List<Variable>[] vars;
                //ClearVars();
                PrepairForVars(out Params, out vars);
                return GetData(ip, Params, vars);
            }
            public static List<Variable>[] GetLog(string ip)                //Return variables for getlog
            {
                List<ObjectIdentifier> Params;
                List<Variable>[] vars;
                //ClearVars();
                PrepairForLogs(out Params, out vars);
                return GetData(ip, Params, vars);
            }

            /// <summary>
            /// Создает список корректировки индексов переменных для корректного сохранения логов.
            /// </summary>
            /// <param name="varList">Список переменных, полученный с устрйоства.</param>
            /// <param name="corList">Список корректировок индексов для каждой переменной.</param>
            /// <returns>Разница между максимальным и минимальным индексом в списке переменных, полученном с устройства.</returns>
            public static int CreateCorrectionIndexes(List<Variable>[] varList, out int[] corList)
            {
                //return
                //-1 - ошибка OID
                corList = new int[varList.Length];
                //corList[0] = int.Parse(varList[0][1].Id.ToString().Remove(0, varList[0][0].Id.ToString().Length + 1));
                var str = varList[0][1].Id.ToString().Split('.');
                corList[0] = Int32.Parse(str[str.Length - 1]);
                int min = corList[0];
                int max = corList[0];
                for (int i = 1; i < varList.Length; i++)
                {
                    str = varList[i][1].Id.ToString().Split('.');
                    if (!Int32.TryParse(str[str.Length - 1], out corList[i]))
                    //if (!int.TryParse(varList[i][1].Id.ToString().Remove(0, varList[i][0].Id.ToString().Length + 1),
                    //                  out corList[i]))
                        return -1;
                    if (corList[i] > max)
                        max = corList[i];
                    if (corList[i] < min)
                        min = corList[i];
                }
                int maxDiff = max - min;
                for (int j = 0; j < corList.Length; j++)
                {
                    corList[j] = max - corList[j];
                }
                return maxDiff;
            }
        }                   //Retrieving data from T-VIPS specified here


        //ToImplement
        public DeviceControl GetController(string ip)
        {
            var controller = new MyDeviceControl();
            controller.IpAddress = ip;
            return controller;
        }

        static string Getstatus(string ip)
        {
            List<Variable>[] vars = StatusData.GetVariables(ip);
            //int[] correctIndexes;
            //var diff = StatusData.CreateCorrectionIndexes(vars, out correctIndexes);
            //if (diff < 0)
            //{
            //    return "err:Получен некорректный ответ от устройства";
            //}
            if (vars[0].Count == 0)
            {
                return Errors.NO_ERRORS;
            }
            if (vars[0][0].Id.ToString() == ".1.3")
                return Errors.ERR_BEG + Errors.NO_CONNECTION;
            int varCount = vars[0].Count;
            if (varCount < 1)
                return Errors.NO_ERRORS;
            var st = new StringBuilder();
            for (int i = 0; i < varCount; i++)
            {
                //st += vars[0][i].Data.ToString() + ":";
                var varStr = new StringBuilder();
                try
                {
                    string sevStr = vars[0][i].Data.ToString();
                    string severity;
                    switch (sevStr)
                    {
                        case "1":
                            //severity = "1=Cleared";
                            //severity = "Cleared";
                            severity = Severity.CLEARED;
                            break;
                        case "2":
                            //severity = "2=Indeterminate";
                            severity = Severity.INDETERMINATE;
                            break;
                        case "3":
                            //severity = "3=Warning";
                            severity = Severity.WARNING;
                            break;
                        case "4":
                            //severity = "4=Minor";
                            severity = Severity.MINOR;
                            break;
                        case "5":
                            //severity = "5=Major";
                            severity = Severity.MAJOR;
                            break;
                        case "6":
                            //severity = "6=Critical";
                            severity = Severity.CRITICAL;
                            break;
                        default:
                            return "err:Ошибка определения приоритета ошибки";
                    }
                    varStr.Append(severity + ":"); //severity
                    varStr.Append(vars[2][i].Data.ToString() + " - "); //source
                    var det = vars[3][i].Data.ToString(); //details
                    if (det.Length < 1)
                        varStr.Append(vars[1][i].Data.ToString() + ";"); //name
                    else
                    {
                        varStr.Append(vars[1][i].Data.ToString() + ". "); //name
                        varStr.Append(det + ";"); //details
                    }
                }
                catch (Exception)
                {
                    continue;
                }
                st.Append(varStr);
            }
            
            return st.ToString();
        }

        string IDeviceInterface.Getparams(string ip)
        {
            return Getparams(ip);
        }

        public static string Getparams(string ip)
        {
            return Errors.NOT_IMPLEMENTED;
        }

        string IDeviceInterface.Getlog(string ip, string logFilePath)
        {
            return Getlog(ip, logFilePath);
        }

        public string TrapHandle(string devName, byte[] serializedTrap, DateTime date)
        {
            TrapV2Message trap;
            try
            {
                trap = MySerializer.Deserialize<TrapV2Message>(serializedTrap);
            }
            catch (Exception)
            {
                return Errors.ERR_BEG + Errors.WRONG_INPUT_DATA + " serializedTrap";
            }
            return TrapHandle(devName, trap, date);
        }

        string IDeviceInterface.Getstatus(string ip)
        {
            return Getstatus(ip);
        }

        /// <summary>
        /// Преобразует trap с устройства в запись лога.
        /// </summary>
        /// <returns></returns>
        static string TrapHandle(string devName, TrapV2Message trap, DateTime date)
        {
            var record = new LogRecord();
            
            var ent = trap.Enterprise.ToString();
            var variables = trap.Scope.Pdu.Variables;

            var dt = new StringBuilder();
            dt.Append(date.Year.ToString(CultureInfo.InvariantCulture) + "-" +
                      date.Month.ToString(CultureInfo.InvariantCulture) + "-" +
                      date.Day.ToString(CultureInfo.InvariantCulture) +
                      " " +
                      date.Hour.ToString(CultureInfo.InvariantCulture) + ":" +
                      date.Minute.ToString(CultureInfo.InvariantCulture) + ":" +
                      date.Second.ToString(CultureInfo.InvariantCulture));

            record.Severity = LogRecord.LogSeverities[variables[(int)LogRecord.LogVar.Severity].Data.ToString()];
            record.Name = variables[(int)LogRecord.LogVar.AlarmName].Data.ToString();
            record.Source = variables[(int)LogRecord.LogVar.SourceText].Data.ToString();
            record.Details = variables[(int)LogRecord.LogVar.Details].Data.ToString();
            record.RefNumber = int.Parse(variables[(int)LogRecord.LogVar.RefNumber].Data.ToString());
            record.OnTime = dt.ToString();
            

            //Появилась авария
            if (String.Compare(ent, LogRecord.UnitAsserted, StringComparison.Ordinal) == 0)
            {
                record.RecordType = LogRecord.ObjectIdType.Asserted;
            }
            else
            //Исправлена авария
            if (String.Compare(ent, LogRecord.UnitCleared, StringComparison.Ordinal) == 0)
            {
                record.RecordType = LogRecord.ObjectIdType.Cleared;

            }
            else
            //Событие без длительности
            if (String.Compare(ent, LogRecord.UnitEvent, StringComparison.Ordinal) == 0)
            {
                record.RecordType = LogRecord.ObjectIdType.Event;
            }

            //Добавление события во временный список
            if (!_trapsMtx.ContainsKey(devName))
                _trapsMtx.Add(devName, new Mutex());
            _trapsMtx[devName].WaitOne();
            try
            {
                //Если в списке нет данных о текущем устройстве
                if (!_recordsFromTraps.ContainsKey(devName))
                    _recordsFromTraps.Add(devName, new Dictionary<int, LogRecord>());

                if (record.RecordType == LogRecord.ObjectIdType.Cleared)
                {
                    if (_recordsFromTraps[devName].ContainsKey(record.RefNumber))
                    {
                        _recordsFromTraps[devName][record.RefNumber].OffTime = record.OnTime;
                        _recordsFromTraps[devName][record.RefNumber].RecordType =
                            LogRecord.ObjectIdType.AssertedAndCleared;
                    }
                    else
                    {
                        _recordsFromTraps[devName].Add(record.RefNumber, record);
                    }
                }
                else
                {
                    if (!_recordsFromTraps[devName].ContainsKey(record.RefNumber))
                        _recordsFromTraps[devName].Add(record.RefNumber, record);
                }
            }
            catch (Exception ex)
            {
                return "serr:" + ex.Message;
            }
            finally
            {
                _trapsMtx[devName].ReleaseMutex();
            }
            

            return "ok";
        }

        static string Getlog(string ip, string logFilePath)
        {
            //var records = new List<LogRecord>();
            
            var tempFilePath = LogRecord.GetTempFilePath(logFilePath);
            var devName = LogRecord.GetDeviceNameFromPath(logFilePath);

            var records = new Dictionary<int, LogRecord>();
            //var oldrecords = LogRecord.ReadFile(tempFilePath);
            
            string curdir = Directory.GetCurrentDirectory();
            var vars = StatusData.GetLog(ip);
            if (vars[0].Count() < 2)
                return "ok";
            if (vars[0][1].Id.ToString() == ".1.3")
            {
                CreateLogs(logFilePath, devName, tempFilePath);
                return "err:Нет связи с устройством";
            }
            int[] correctIndexes;
            var diff = StatusData.CreateCorrectionIndexes(vars, out correctIndexes);
            if (diff < 0)
            {
                CreateLogs(logFilePath, devName, tempFilePath);
                return "err:Получен некорректный ответ от устройства";
            }
            try
            {
                int i = File.Exists(logFilePath) ? 1 : 0;
                int varCount = vars[0].Count;
                for (; i < varCount - diff; i++)
                {
                    int j = 0;
                    int fieldsCount = vars.Count();
                    var record = new LogRecord();
                    while (j < fieldsCount)
                    {

                        try
                        {
                            if (i != 0)
                                switch (vars[j][0].Data.ToString())
                                {
                                    case "Time":
                                        byte[] time = vars[j][i + correctIndexes[j]].Data.ToBytes();
                                        var year = new[] {time[3], time[2]};
                                        var date = new DateTime(BitConverter.ToInt16(year, 0), time[4], time[5], time[6],
                                                                time[7], time[8]);
                                        var dt = new StringBuilder();
                                        dt.Append(date.Year.ToString(CultureInfo.InvariantCulture) + "-" +
                                                  date.Month.ToString(CultureInfo.InvariantCulture) + "-" +
                                                  date.Day.ToString(CultureInfo.InvariantCulture) +
                                                  " " +
                                                  date.Hour.ToString(CultureInfo.InvariantCulture) + ":" +
                                                  date.Minute.ToString(CultureInfo.InvariantCulture) + ":" +
                                                  date.Second.ToString(CultureInfo.InvariantCulture));

                                        record.OnTime = dt.ToString();
                                        break;

                                    case "ObjectId":
                                        //Появилась авария
                                        if (String.Compare(vars[j][i + correctIndexes[j]].Data.ToString(),
                                                           LogRecord.UnitAsserted,
                                                           StringComparison.Ordinal) == 0)
                                        {
                                            record.RecordType = LogRecord.ObjectIdType.Asserted;
                                        }
                                        //Исправлена авария
                                        if (String.Compare(vars[j][i + correctIndexes[j]].Data.ToString(),
                                                           LogRecord.UnitCleared,
                                                           StringComparison.Ordinal) == 0)
                                        {
                                            record.RecordType = LogRecord.ObjectIdType.Cleared;
                                        }
                                        //Событие без длительности
                                        if (String.Compare(vars[j][i + correctIndexes[j]].Data.ToString(),
                                                           LogRecord.UnitEvent,
                                                           StringComparison.Ordinal) == 0)
                                        {
                                            record.RecordType = LogRecord.ObjectIdType.Event;
                                        }
                                        break;

                                    case "Severity":
                                        string str = "";
                                        switch (vars[j][i + correctIndexes[j]].Data.ToString())
                                        {
                                            case "1":
                                                str = "Cleared";
                                                break;
                                            case "2":
                                                str = "Indeterminate";
                                                break;
                                            case "3":
                                                str = "Warning";
                                                break;
                                            case "4":
                                                str = "Minor";
                                                break;
                                            case "5":
                                                str = "Major";
                                                break;
                                            case "6":
                                                str = "Critical";
                                                break;
                                        }
                                        record.Severity = str;
                                        break;

                                    case "Name":
                                        record.Name = vars[j][i + correctIndexes[j]].Data.ToString();
                                        break;

                                    case "Source":
                                        record.Source = vars[j][i + correctIndexes[j]].Data.ToString();
                                        break;

                                    case "Details":
                                        record.Details = vars[j][i + correctIndexes[j]].Data.ToString();
                                        break;

                                    case "RefNumber":
                                        record.RefNumber = int.Parse(vars[j][i + correctIndexes[j]].Data.ToString());
                                        break;
                                }

                            j++;
                        }
                        catch (IndexOutOfRangeException)
                        {
                            break;
                        }
                    }
                    if (i != 0)
                    {
                        if (record.RecordType == LogRecord.ObjectIdType.Cleared)
                        {
                            if (records.ContainsKey(record.RefNumber))
                            {
                                records[record.RefNumber].OffTime = record.OnTime;
                                records[record.RefNumber].RecordType = LogRecord.ObjectIdType.AssertedAndCleared;
                            }
                            else
                            {
                                records.Add(record.RefNumber, record);
                            }
                        }
                        else
                        {
                            if (!records.ContainsKey(record.RefNumber))
                            {
                                records.Add(record.RefNumber, record);
                            }
                        }
                    }
                }
                //Запись полученных данных
                CreateLogs(logFilePath, devName, tempFilePath, records);
            }
            catch (IndexOutOfRangeException)
            {
            }
            catch (Exception ex)
            {
                return Errors.ERR_BEG + ex.Message + ": " + devName;
            }
            finally
            {
                Directory.SetCurrentDirectory(curdir);
            }
            
            return "ok";
        }

        /// <summary>
        /// Ипользуя полученные от прибора данные записывает их в файл.
        /// </summary>
        /// <param name="logFilePath">Файл, в который записывается лог для сервера.</param>
        /// <param name="devName">Имя устройства.</param>
        /// <param name="tempFilePath">Пусть к временному файлу.</param>
        /// <param name="records">Список записей, полученных без ловушек.</param>
        private static void CreateLogs(string logFilePath, string devName, string tempFilePath, Dictionary<int, LogRecord> records = null)
        {
            //Dictionary<int, LogRecord> oldrecords;
            var anyTraps = false;                              //Флаг наличия записей из ловушек (traps)
            var oldrecords = LogRecord.ReadFile(tempFilePath);
            //Мьютекс для работы со списком логов от ловушек (trap) snmp
            //Создать мьютекс, если нет
            if (!_trapsMtx.ContainsKey(devName))
                _trapsMtx.Add(devName, new Mutex());
            _trapsMtx[devName].WaitOne();

            try
            {
                if (_recordsFromTraps.ContainsKey(devName))
                {
                    if (_recordsFromTraps[devName].Any())
                    {
                        anyTraps = true;
                        //Корректировка временного списка по ловушкам
                        LogRecord.CorrectList(ref oldrecords, _recordsFromTraps[devName]);
                        //Очистка списка логов, полученных от ловушек (trap) snmp
                        _recordsFromTraps[devName].Clear();
                    }
                }
            }
            finally
            {
                _trapsMtx[devName].ReleaseMutex();
            }

            //Корректировка временного списка по логам
            if(records != null)
                LogRecord.CorrectList(ref oldrecords, records);
            else
            {
                if (!anyTraps)
                    return;
            }

            //Запись нового файла логов
            using (var sw = new StreamWriter(logFilePath, false, Encoding.Default))
            {
                sw.WriteLine("Severity;Name;Source;Details;Time;OffTime");
                foreach (var oldrecord in oldrecords)
                {
                    sw.WriteLine(oldrecord.Value.ToString());
                }
            }

            //var tempFilePath = LogRecord.GetTempFilePath(logFilePath);
            if (!_tempFiles.Contains(tempFilePath))
                _tempFiles.Add(tempFilePath);

            using (var sw = new StreamWriter(tempFilePath, false, Encoding.Default))
            {
                foreach (var oldrecord in oldrecords)
                {
                    sw.WriteLine(oldrecord.Value.ToString() + oldrecord.Value.RefNumber + ";");
                }
            }
        }

        /// <summary>
        /// Удаление всех временных ресурсов.
        /// </summary>
        /// <returns></returns>
        private static string Flush()
        {
            if (_trapsMtx.Count > 0)
            {

                foreach (var mutex in _trapsMtx)
                {
                    mutex.Value.Close();
                }
                _trapsMtx.Clear();
            }

            var sb = new StringBuilder();
            if (_tempFiles.Count > 0)
            {
                foreach (var tempFile in _tempFiles)
                {
                    try
                    {
                        if (File.Exists(tempFile))
                            File.Delete(tempFile);
                        sb.AppendLine(tempFile);
                    }
                    catch (Exception ex)
                    {
                        //var str = tempFile.Split('\\');
                        return Errors.ERR_BEG + ex.Message;
                    }
                }

                try
                {
                    if (Directory.Exists((new FileInfo(_tempFiles[0])).Directory.ToString()))
                        Directory.Delete((new FileInfo(_tempFiles[0])).Directory.ToString());
                }
                catch (Exception ex)
                {
                    return Errors.ERR_BEG + ex.Message + ": " + (new FileInfo(_tempFiles[0])).Directory.Name;
                }

                _tempFiles.Clear();
            }
            return "ok";
        }

        [Obfuscation(Feature = "DllExport")]
        public static string CallMethod(string func, params object[] pars)
        {
            if (!File.Exists("Resources\\Libs\\SharpSnmpLib.dll") && !File.Exists("SharpSnmpLib.dll"))
                return "err:Библиотека SharpSnmpLib.dll не найдена";
            string ret;
            switch (func)
            {
                case "getstatus":
                    try
                    {
                        ret = Getstatus(pars[0].ToString());
                        return ret;
                    }
                    catch (Exception ex)
                    {
                        if (ex is IndexOutOfRangeException)
                            return "err:Неверное количество аргументов";
                        return Errors.ERR_BEG + ex.Message;
                    }
                case "getparams":
                    try
                    {
                        ret = Getparams(pars[0].ToString());
                        return ret;
                    }
                    catch (Exception ex)
                    {
                        if (ex is IndexOutOfRangeException)
                            return "err:Неверное количество аргументов";
                        return Errors.ERR_BEG + ex.Message;
                    }
                case "traphandle":
                    try
                    {
                        ret = TrapHandle(pars[0] as string, pars[1] as TrapV2Message, (DateTime)pars[2]);
                        return ret;
                    }
                    catch (Exception ex)
                    {
                        if (ex is IndexOutOfRangeException)
                            return "err:Неверное количество аргументов";
                        return Errors.ERR_BEG + ex.Message;
                    }
                case "getlog":
                    try
                    {
                        ret = Getlog(pars[0] as string, pars[1] as string);
                        return ret;
                    }
                    catch (Exception ex)
                    {
                        if (ex is IndexOutOfRangeException)
                            return "err:Неверное количество аргументов";
                        return Errors.ERR_BEG + ex.Message;
                    }
                case "flush":
                    try
                    {
                        ret = Flush();
                        return ret;
                    }
                    catch (Exception ex)
                    {
                        return Errors.ERR_BEG + ex.Message;
                    }
                default:
                    return "err:Такой функции не существует";
            }
        }

        class MyDeviceControl : DeviceControl
        {
            public string IpAddress { get; set; }


            public override ControlType GetControlType
            {
                get { return ControlType.NetworkLink;}
            }

            public override object GetControl(CultureInfo cultureInfo = null)
            {
                //http://192.168.2.251/
                return @"http://" + IpAddress + @"/";
            }

            public override string ShowControl()
            {
                return Messages.NOTHING_HERE;
            }

            public override List<ParamInfo> GetParametersList()
            {
                return null;
            }

            public override string GetParametersString()
            {
                return Messages.NOTHING_HERE;
            }

            public override string SetParameter(string paramName, string paramValue)
            {
                return Messages.NOTHING_HERE;
            }
        }

    }
}
